#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
物品路由

这个模块包含物品管理相关的 API 端点：
1. 创建物品
2. 获取物品列表
3. 获取物品详情
4. 更新物品信息
5. 删除物品
6. 物品搜索
7. 物品统计

支持分页、搜索、排序、筛选等功能
包含权限控制和数据验证

作者: FastAPI 学习项目
创建时间: 2024
"""

from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from pydantic import BaseModel
from loguru import logger

from app.database.connection import get_db
from app.database.crud import crud_item, crud_user
from app.models.user import User
from app.models.item import (
    Item, ItemCreate, ItemUpdate, ItemResponse, 
    ItemWithOwner, ItemSearch, ItemStats
)
from app.utils.security import get_current_active_user, get_current_superuser
from app.utils.helpers import create_pagination_response
from config import settings

# 创建路由器
router = APIRouter()


# Pydantic 模型
class ItemListResponse(BaseModel):
    """
    物品列表响应模型
    """
    items: List[ItemWithOwner]
    total: int
    page: int
    size: int
    pages: int


class ItemSearchResponse(BaseModel):
    """
    物品搜索响应模型
    """
    items: List[ItemWithOwner]
    total: int
    query: str
    page: int
    size: int


class MessageResponse(BaseModel):
    """
    消息响应模型
    """
    message: str


class TagsResponse(BaseModel):
    """
    标签响应模型
    """
    tags: List[str]
    total: int


class CategoriesResponse(BaseModel):
    """
    分类响应模型
    """
    categories: List[dict]
    total: int


@router.post(
    "/",
    response_model=ItemResponse,
    status_code=status.HTTP_201_CREATED,
    summary="创建物品",
    description="创建新的物品"
)
async def create_item(
    item_in: ItemCreate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    创建物品
    
    创建一个新的物品，物品的所有者将设置为当前登录用户。
    
    Args:
        item_in: 物品创建数据
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemResponse: 创建的物品信息
        
    Raises:
        HTTPException: 当创建失败时抛出 500 错误
        
    Example:
        ```json
        {
            "title": "我的第一个物品",
            "description": "这是一个示例物品",
            "category": "电子产品",
            "tags": ["手机", "智能"],
            "price": 999.99,
            "is_available": true
        }
        ```
    """
    try:
        logger.info(f"创建物品请求: {item_in.title}, 创建者={current_user.username}")
        
        # 创建物品
        item = crud_item.create_with_owner(
            db, 
            obj_in=item_in, 
            owner_id=current_user.id
        )
        
        logger.info(f"物品创建成功: {item.title} (ID: {item.id})")
        
        return item
        
    except Exception as e:
        logger.error(f"创建物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="创建物品失败，请稍后重试"
        )


@router.get(
    "/",
    response_model=ItemListResponse,
    summary="获取物品列表",
    description="获取物品的分页列表"
)
async def get_items(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(10, ge=1, le=100, description="每页数量"),
    category: Optional[str] = Query(None, description="筛选分类"),
    is_available: Optional[bool] = Query(None, description="筛选可用状态"),
    min_price: Optional[float] = Query(None, ge=0, description="最低价格"),
    max_price: Optional[float] = Query(None, ge=0, description="最高价格"),
    tags: Optional[str] = Query(None, description="筛选标签（逗号分隔）"),
    sort_by: str = Query("created_at", description="排序字段"),
    sort_order: str = Query("desc", regex="^(asc|desc)$", description="排序方向"),
    owner_only: bool = Query(False, description="只显示自己的物品"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取物品列表
    
    返回分页的物品列表，支持多种筛选和排序选项。
    
    Args:
        page: 页码（从1开始）
        size: 每页数量（1-100）
        category: 筛选分类
        is_available: 筛选可用状态
        min_price: 最低价格
        max_price: 最高价格
        tags: 筛选标签（逗号分隔）
        sort_by: 排序字段
        sort_order: 排序方向（asc/desc）
        owner_only: 只显示自己的物品
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemListResponse: 分页的物品列表
    """
    try:
        logger.info(f"获取物品列表请求: page={page}, size={size}, 请求者={current_user.username}")
        
        # 计算偏移量
        skip = (page - 1) * size
        
        # 构建筛选条件
        filters = {}
        if category:
            filters['category'] = category
        if is_available is not None:
            filters['is_available'] = is_available
        if min_price is not None:
            filters['min_price'] = min_price
        if max_price is not None:
            filters['max_price'] = max_price
        if owner_only:
            filters['owner_id'] = current_user.id
        
        # 处理标签筛选
        tag_list = None
        if tags:
            tag_list = [tag.strip() for tag in tags.split(',') if tag.strip()]
        
        # 获取物品列表
        items = crud_item.get_multi(
            db,
            skip=skip,
            limit=size,
            filters=filters,
            tags=tag_list,
            sort_by=sort_by,
            sort_order=sort_order
        )
        
        # 获取总数
        total = crud_item.count(db, filters=filters, tags=tag_list)
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        logger.info(f"物品列表获取成功: 返回 {len(items)} 个物品，总计 {total} 个")
        
        return {
            "items": items,
            "total": total,
            "page": page,
            "size": size,
            "pages": pages
        }
        
    except Exception as e:
        logger.error(f"获取物品列表异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取物品列表失败"
        )


@router.get(
    "/my-items",
    response_model=ItemListResponse,
    summary="获取我的物品",
    description="获取当前用户的物品列表"
)
async def get_my_items(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(10, ge=1, le=100, description="每页数量"),
    category: Optional[str] = Query(None, description="筛选分类"),
    is_available: Optional[bool] = Query(None, description="筛选可用状态"),
    sort_by: str = Query("created_at", description="排序字段"),
    sort_order: str = Query("desc", regex="^(asc|desc)$", description="排序方向"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取我的物品
    
    返回当前用户拥有的物品列表。
    
    Args:
        page: 页码（从1开始）
        size: 每页数量（1-100）
        category: 筛选分类
        is_available: 筛选可用状态
        sort_by: 排序字段
        sort_order: 排序方向（asc/desc）
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemListResponse: 分页的物品列表
    """
    try:
        logger.info(f"获取我的物品请求: page={page}, size={size}, 用户={current_user.username}")
        
        # 计算偏移量
        skip = (page - 1) * size
        
        # 获取用户的物品
        items = crud_item.get_by_owner(
            db,
            owner_id=current_user.id,
            skip=skip,
            limit=size,
            category=category,
            is_available=is_available,
            sort_by=sort_by,
            sort_order=sort_order
        )
        
        # 获取总数
        filters = {'owner_id': current_user.id}
        if category:
            filters['category'] = category
        if is_available is not None:
            filters['is_available'] = is_available
        
        total = crud_item.count(db, filters=filters)
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        logger.info(f"我的物品获取成功: 返回 {len(items)} 个物品，总计 {total} 个")
        
        return {
            "items": items,
            "total": total,
            "page": page,
            "size": size,
            "pages": pages
        }
        
    except Exception as e:
        logger.error(f"获取我的物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取我的物品失败"
        )


@router.get(
    "/{item_id}",
    response_model=ItemWithOwner,
    summary="获取物品详情",
    description="根据物品ID获取物品详细信息"
)
async def get_item(
    item_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取物品详情
    
    根据物品ID获取物品的详细信息，包括所有者信息。
    
    Args:
        item_id: 物品ID
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemWithOwner: 物品详细信息（包含所有者信息）
        
    Raises:
        HTTPException: 当物品不存在时抛出 404 错误
    """
    try:
        logger.info(f"获取物品详情请求: item_id={item_id}, 请求者={current_user.username}")
        
        # 获取物品
        item = crud_item.get_with_owner(db, id=item_id)
        if not item:
            logger.warning(f"物品不存在: {item_id}")
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="物品不存在"
            )
        
        logger.info(f"物品详情获取成功: {item.title}")
        return item
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取物品详情异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取物品详情失败"
        )


@router.put(
    "/{item_id}",
    response_model=ItemResponse,
    summary="更新物品信息",
    description="更新物品信息（只有物品所有者或超级用户可以操作）"
)
async def update_item(
    item_id: int,
    item_update: ItemUpdate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    更新物品信息
    
    允许物品所有者或超级用户更新物品信息。
    
    Args:
        item_id: 物品ID
        item_update: 物品更新数据
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemResponse: 更新后的物品信息
        
    Raises:
        HTTPException: 当物品不存在或权限不足时抛出相应错误
        
    Example:
        ```json
        {
            "title": "更新的物品标题",
            "description": "更新的描述",
            "price": 1299.99,
            "is_available": false
        }
        ```
    """
    try:
        logger.info(f"更新物品请求: item_id={item_id}, 操作者={current_user.username}")
        
        # 获取物品
        item = crud_item.get(db, id=item_id)
        if not item:
            logger.warning(f"物品不存在: {item_id}")
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="物品不存在"
            )
        
        # 权限检查：只有物品所有者或超级用户可以更新
        if item.owner_id != current_user.id and not current_user.is_superuser:
            logger.warning(f"权限不足: {current_user.username} 尝试更新物品 {item_id}")
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足，只有物品所有者可以更新"
            )
        
        # 更新物品
        updated_item = crud_item.update(db, db_obj=item, obj_in=item_update)
        logger.info(f"物品更新成功: {updated_item.title} (操作者: {current_user.username})")
        
        return updated_item
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新物品失败"
        )


@router.delete(
    "/{item_id}",
    response_model=MessageResponse,
    summary="删除物品",
    description="删除物品（只有物品所有者或超级用户可以操作）"
)
async def delete_item(
    item_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    删除物品
    
    允许物品所有者或超级用户删除物品。
    
    Args:
        item_id: 物品ID
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        MessageResponse: 删除成功消息
        
    Raises:
        HTTPException: 当物品不存在或权限不足时抛出相应错误
    """
    try:
        logger.info(f"删除物品请求: item_id={item_id}, 操作者={current_user.username}")
        
        # 获取物品
        item = crud_item.get(db, id=item_id)
        if not item:
            logger.warning(f"物品不存在: {item_id}")
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="物品不存在"
            )
        
        # 权限检查：只有物品所有者或超级用户可以删除
        if item.owner_id != current_user.id and not current_user.is_superuser:
            logger.warning(f"权限不足: {current_user.username} 尝试删除物品 {item_id}")
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足，只有物品所有者可以删除"
            )
        
        # 删除物品
        crud_item.remove(db, id=item_id)
        logger.info(f"物品删除成功: {item.title} (操作者: {current_user.username})")
        
        return {"message": f"物品 '{item.title}' 已被删除"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="删除物品失败"
        )


@router.get(
    "/search/",
    response_model=ItemSearchResponse,
    summary="搜索物品",
    description="根据关键词搜索物品"
)
async def search_items(
    q: str = Query(..., min_length=1, description="搜索关键词"),
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(10, ge=1, le=50, description="每页数量"),
    category: Optional[str] = Query(None, description="筛选分类"),
    min_price: Optional[float] = Query(None, ge=0, description="最低价格"),
    max_price: Optional[float] = Query(None, ge=0, description="最高价格"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    搜索物品
    
    根据标题、描述或标签搜索物品。
    
    Args:
        q: 搜索关键词
        page: 页码（从1开始）
        size: 每页数量（1-50）
        category: 筛选分类
        min_price: 最低价格
        max_price: 最高价格
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemSearchResponse: 搜索结果
    """
    try:
        logger.info(f"搜索物品请求: q='{q}', page={page}, size={size}, 请求者={current_user.username}")
        
        # 计算偏移量
        skip = (page - 1) * size
        
        # 构建筛选条件
        filters = {}
        if category:
            filters['category'] = category
        if min_price is not None:
            filters['min_price'] = min_price
        if max_price is not None:
            filters['max_price'] = max_price
        
        # 搜索物品
        items, total = crud_item.search(
            db,
            query=q,
            skip=skip,
            limit=size,
            filters=filters
        )
        
        logger.info(f"物品搜索完成: 找到 {total} 个结果，返回 {len(items)} 个")
        
        return {
            "items": items,
            "total": total,
            "query": q,
            "page": page,
            "size": size
        }
        
    except Exception as e:
        logger.error(f"搜索物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="搜索物品失败"
        )


@router.get(
    "/stats/overview",
    response_model=ItemStats,
    summary="获取物品统计",
    description="获取物品统计信息"
)
async def get_item_stats(
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取物品统计
    
    返回物品相关的统计信息。
    
    Args:
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemStats: 物品统计信息
    """
    try:
        logger.info(f"获取物品统计请求: 请求者={current_user.username}")
        
        # 获取统计数据
        stats = crud_item.get_stats(db)
        
        logger.info(f"物品统计获取成功: {stats}")
        
        return stats
        
    except Exception as e:
        logger.error(f"获取物品统计异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取物品统计失败"
        )


@router.get(
    "/categories/",
    response_model=CategoriesResponse,
    summary="获取分类列表",
    description="获取所有物品分类及其统计信息"
)
async def get_categories(
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取分类列表
    
    返回所有物品分类及其统计信息。
    
    Args:
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        CategoriesResponse: 分类列表和统计信息
    """
    try:
        logger.info(f"获取分类列表请求: 请求者={current_user.username}")
        
        # 获取分类统计
        categories = crud_item.get_category_stats(db)
        
        logger.info(f"分类列表获取成功: 找到 {len(categories)} 个分类")
        
        return {
            "categories": categories,
            "total": len(categories)
        }
        
    except Exception as e:
        logger.error(f"获取分类列表异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取分类列表失败"
        )


@router.get(
    "/tags/popular",
    response_model=TagsResponse,
    summary="获取热门标签",
    description="获取最受欢迎的标签列表"
)
async def get_popular_tags(
    limit: int = Query(20, ge=1, le=100, description="返回数量"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取热门标签
    
    返回最受欢迎的标签列表。
    
    Args:
        limit: 返回的标签数量
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        TagsResponse: 热门标签列表
    """
    try:
        logger.info(f"获取热门标签请求: limit={limit}, 请求者={current_user.username}")
        
        # 获取热门标签
        tags = crud_item.get_popular_tags(db, limit=limit)
        
        logger.info(f"热门标签获取成功: 找到 {len(tags)} 个标签")
        
        return {
            "tags": tags,
            "total": len(tags)
        }
        
    except Exception as e:
        logger.error(f"获取热门标签异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取热门标签失败"
        )


@router.get(
    "/available/",
    response_model=ItemListResponse,
    summary="获取可用物品",
    description="获取所有可用的物品列表"
)
async def get_available_items(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(10, ge=1, le=100, description="每页数量"),
    category: Optional[str] = Query(None, description="筛选分类"),
    min_price: Optional[float] = Query(None, ge=0, description="最低价格"),
    max_price: Optional[float] = Query(None, ge=0, description="最高价格"),
    sort_by: str = Query("created_at", description="排序字段"),
    sort_order: str = Query("desc", regex="^(asc|desc)$", description="排序方向"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取可用物品
    
    返回所有标记为可用的物品列表。
    
    Args:
        page: 页码（从1开始）
        size: 每页数量（1-100）
        category: 筛选分类
        min_price: 最低价格
        max_price: 最高价格
        sort_by: 排序字段
        sort_order: 排序方向（asc/desc）
        current_user: 当前登录用户
        db: 数据库会话
        
    Returns:
        ItemListResponse: 分页的可用物品列表
    """
    try:
        logger.info(f"获取可用物品请求: page={page}, size={size}, 请求者={current_user.username}")
        
        # 计算偏移量
        skip = (page - 1) * size
        
        # 构建筛选条件
        filters = {'is_available': True}
        if category:
            filters['category'] = category
        if min_price is not None:
            filters['min_price'] = min_price
        if max_price is not None:
            filters['max_price'] = max_price
        
        # 获取可用物品
        items = crud_item.get_available(
            db,
            skip=skip,
            limit=size,
            filters=filters,
            sort_by=sort_by,
            sort_order=sort_order
        )
        
        # 获取总数
        total = crud_item.count(db, filters=filters)
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        logger.info(f"可用物品获取成功: 返回 {len(items)} 个物品，总计 {total} 个")
        
        return {
            "items": items,
            "total": total,
            "page": page,
            "size": size,
            "pages": pages
        }
        
    except Exception as e:
        logger.error(f"获取可用物品异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取可用物品失败"
        )